package cn.dq.demo.design.singleton;

import org.springframework.stereotype.Component;

@Component
//懒汉式（只有调用方法了才会创建对象，有线程安全问题）
public class LazySingletonDesign {

    private String name;

    public String getName() {
        return name;
    }

    //私有set不让别人设置
    private void setName(String name) {
        this.name = name;
    }

    //私有构造函数让别人不能实例化
    private LazySingletonDesign() {

    }

    //静态
    private static LazySingletonDesign lazySingletonDesign = null;

    //静态方法让别人调用（最基础的同步方式，但是每次进入都会验证锁，性能差）
    public static synchronized LazySingletonDesign getSingleInstance(String name) {
        if (lazySingletonDesign == null) {
            lazySingletonDesign = new LazySingletonDesign();
            lazySingletonDesign.setName(name);
            return lazySingletonDesign;
        }
        return lazySingletonDesign;
    }

    //静态方法让别人调用
    //双重锁机制，singleton这个变量要用volatile修饰，表示变量将不会被本地线程缓存，所有对该变量的读写都是直接操作共享内存
    //性能好一点，只有第一次实例化时需要验证同步
    //PS:由于volatile关键字可能会屏蔽掉虚拟机中一些必要的代码优化，所以运行效率并不是很高。
    // 因此一般建议，没有特别的需要，不要使用。也就是说，虽然可以使用“双重检查加锁”机制来实现线程安全的单例，但并不建议大量采用，可以根据情况来选用。
    public static LazySingletonDesign getSingletonDesign1(String name) {
        if (lazySingletonDesign == null) {
            synchronized (LazySingletonDesign.class) {
                //再次检查实例是否存在，如果不存在才真正的创建实例
                if (lazySingletonDesign == null) {
                    lazySingletonDesign = new LazySingletonDesign();
                    lazySingletonDesign.setName(name);
                    return lazySingletonDesign;
                }
            }
        }
        return lazySingletonDesign;
    }

}
